package xyz.tommy0607.calculator.view

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import xyz.tommy0607.calculator.R
import xyz.tommy0607.calculator.util.UiExt
import kotlin.math.min

class RoundButton : View {
    private val circlePaint = Paint()
    private val textPaint = Paint()
    private val veilPaint = Paint()
    private var radius = 0f
    private val textWidths = FloatArray(1)
    private var padding = 0f
    private var character = '0'

    companion object {
        private const val DEFAULT_CIRCLE_COLOR_NORMAL = 0xFF333333.toInt()
        private const val DEFAULT_TEXT_COLOR = 0xFFFCFCFC.toInt()
        private const val DEFAULT_VEIL_COLOR = 0xFFFFFFFF.toInt()
        private const val DEFAULT_PADDING_IN_DP = 8
        private const val VEIL_ALPHA = 75
    }

    constructor(context: Context) : super(context) {
        init(null)
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init(attrs)
    }

    private fun init(attrs: AttributeSet?) {
        var circleColor= DEFAULT_CIRCLE_COLOR_NORMAL
        var textColor= DEFAULT_TEXT_COLOR
        if (attrs != null) {
            val defaultPadding = UiExt.dp2px(context, DEFAULT_PADDING_IN_DP)
            val typedArray = resources.obtainAttributes(attrs, R.styleable.RoundButton)
            padding = typedArray.getDimension(R.styleable.RoundButton_padding, defaultPadding)
            circleColor = typedArray.getColor(R.styleable.RoundButton_circleColor, DEFAULT_CIRCLE_COLOR_NORMAL)
            textColor = typedArray.getColor(R.styleable.RoundButton_textColor, DEFAULT_TEXT_COLOR)
            val str = typedArray.getString(R.styleable.RoundButton_character)
            if (str != null && str.isNotEmpty()) {
                character = str[0]
            }
            typedArray.recycle()
        }
        circlePaint.color = circleColor
        textPaint.color = textColor
        veilPaint.color = DEFAULT_VEIL_COLOR
        veilPaint.alpha = 0
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
        val widthMode = MeasureSpec.getMode(widthMeasureSpec)

        val heightSize = MeasureSpec.getSize(heightMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        var width = 0
        if (widthMode == MeasureSpec.EXACTLY && heightMeasureSpec == MeasureSpec.EXACTLY) {
            width = min(widthSize, heightSize)
        } else if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
            width = UiExt.dp2px(context, 100).toInt()
        } else if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize
        } else if (heightMode == MeasureSpec.EXACTLY) {
            width = heightSize
        }
        radius = width / 2 - padding
        setMeasuredDimension(width, width)

        textPaint.textSize = radius
        textPaint.getTextWidths("$character", textWidths)
    }

    override fun onDraw(canvas: Canvas?) {
        if (canvas == null) return
        canvas.drawCircle(radius + padding, radius + padding, radius, circlePaint)
        canvas.drawCircle(radius + padding, radius + padding, radius, veilPaint)
        canvas.drawText("$character", radius + padding - textWidths[0] / 2, radius + padding + textWidths[0] / 2, textPaint)
    }

    private var insideView = true

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        if (event == null) return true
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                insideView = true
                veilPaint.alpha = VEIL_ALPHA
                invalidate()
            }
            MotionEvent.ACTION_MOVE -> {
                if (!isTouchPointInCircle(event.x.toInt(), event.y.toInt()) && insideView) {
                    insideView = false
                    returnToNormal()
                }
            }
            MotionEvent.ACTION_UP -> {
                if (insideView) {
                    returnToNormal()
                    performClick()
                }
            }
        }
        return true
    }

    private fun returnToNormal() {
        val valueAnimator = ValueAnimator.ofInt( VEIL_ALPHA,0)
        valueAnimator.duration = 200
        valueAnimator.addUpdateListener {
            veilPaint.alpha = it.animatedValue as Int
            invalidate()
        }
        valueAnimator.start()
    }

    private fun isTouchPointInCircle(x: Int, y: Int): Boolean {
        return Math.pow((x - radius - padding).toDouble(), 2.0) +
                Math.pow((y - radius - padding).toDouble(), 2.0) <= radius * radius
    }

    public fun setCircleColor(newCircleColor:Int){
        circlePaint.color=newCircleColor
        invalidate()
    }

    public fun setCircleColorWithAnimation(newCircleColor:Int){
        if(newCircleColor==circlePaint.color)return
        val valueAnimator=ValueAnimator.ofArgb(circlePaint.color,newCircleColor)
        valueAnimator.duration=500
        valueAnimator.addUpdateListener {
            circlePaint.color=it.animatedValue as Int
            invalidate()
        }
        valueAnimator.start()
    }

    public fun setTextColor(newTextColor:Int){
        textPaint.color=newTextColor
        invalidate()
    }

    public fun setTextColorWithAnimation(newTextColor:Int){
        if(newTextColor==textPaint.color)return
        val valueAnimator=ValueAnimator.ofArgb(textPaint.color,newTextColor)
        valueAnimator.duration=500
        valueAnimator.addUpdateListener {
            textPaint.color=it.animatedValue as Int
            //invalidate()
        }
        valueAnimator.start()
    }
}